/*
 * grafo.cpp
 *
 *  Created on: 17/05/2014
 *      Author: jubuntu
 */

#include "Grafo.h"

int contador = 0;


Grafo::Grafo(){
	this->vectorClonados = new VectorNodos();

	this->matrizDeNodos = new MatrizNodos();
	for(int i = 0; i < FILAS_INICIALES; i++){
		std::vector<Nodo*>* unVector = new std::vector<Nodo*>(COLUMNAS_INICIALES);
		for(int j = 0; j < COLUMNAS_INICIALES; j++){
			Nodo* unNodo = new Nodo();
			unVector->at(j) = unNodo;
		}
		matrizDeNodos->push_back(unVector);
	}


	for(int i = 0; i < FILAS_INICIALES - 1; i++){
		//INICIALIZO LA PRIMERA MITAD DE LAS COLUMNAS
		for(int j = 0; j < COLUMNAS_INICIALES / 2; j++){
			matrizDeNodos->at(i)->at(j)->nodo0 = matrizDeNodos->at(i+1)->at(j*2);
			matrizDeNodos->at(i)->at(j)->nodo1 = matrizDeNodos->at(i+1)->at(j*2+1);
		}
		//INICIALIZO LA SEGUNDA MITAD DE LAS COLUMNAS
		for(int j = COLUMNAS_INICIALES / 2; j < COLUMNAS_INICIALES; j++){
			matrizDeNodos->at(i)->at(j)->nodo0 = matrizDeNodos->at(i+1)->at((j-(COLUMNAS_INICIALES / 2))*2);
			matrizDeNodos->at(i)->at(j)->nodo1 = matrizDeNodos->at(i+1)->at((j-COLUMNAS_INICIALES / 2)*2+1);
		}
	}


	//INICIALIZO LA ULTIMA FILA
	for(int j = 0; j < COLUMNAS_INICIALES / 2; j++){
		matrizDeNodos->at(FILAS_INICIALES -1 )->at(j)->nodo0 = matrizDeNodos->at(0)->at(j*2);
		matrizDeNodos->at(FILAS_INICIALES -1 )->at(j)->nodo1 = matrizDeNodos->at(0)->at(j*2+1);
	}
	for(int j = COLUMNAS_INICIALES / 2; j < COLUMNAS_INICIALES; j++){
		matrizDeNodos->at(FILAS_INICIALES -1 )->at(j)->nodo0 = matrizDeNodos->at(0)->at((j-COLUMNAS_INICIALES / 2)*2);
		matrizDeNodos->at(FILAS_INICIALES -1 )->at(j)->nodo1 = matrizDeNodos->at(0)->at((j-COLUMNAS_INICIALES / 2)*2+1);
	}

	this->nodoActual = matrizDeNodos->at(0)->at(0);
	this->nodoSgte = NULL;

}

Grafo::~Grafo(){

	//ELIMININAMOS CONTENIDO DE LA MATRIZ
	for(int i = 0 ; i < FILAS_INICIALES; i++){
		for(int j = 0; j < COLUMNAS_INICIALES; j++){
			delete matrizDeNodos->at(i)->at(j);
		}
	}

	//ELIMINAMOS CADA FILA DE LA MATRIZ
	for(int i = 0; i < FILAS_INICIALES; i++){
		delete matrizDeNodos->at(i);
	}

	//CHAU MATRIZ
	delete this->matrizDeNodos;

	//ELIMINAMOS CONTENIDO DEL VECTOR
	for(unsigned int i = 0; i < vectorClonados->size(); i++){
		delete vectorClonados->at(i);
	}

	//CHAU VECTOR
	delete this->vectorClonados;

	std::cout << "clone: " << contador << std::endl;
}


void Grafo::clonar(){
	Nodo* nodoNuevo = new Nodo();
	int apuntanAlHijo = this->nodoSgte->frecuenciaCero + this->nodoSgte->frecuenciaUno;
	double r;
	if(this->nodoActual->nodo0 == this->nodoSgte){
		r = (double)this->nodoActual->frecuenciaCero /  (double)(apuntanAlHijo)  ;
		this->nodoActual->nodo0 = nodoNuevo;
	}else{
		r =  (double)this->nodoActual->frecuenciaUno / (double)(apuntanAlHijo);
		this->nodoActual->nodo1 = nodoNuevo;
	}

	nodoNuevo->frecuenciaCero = this->nodoSgte->frecuenciaCero * r;
	this->nodoSgte->frecuenciaCero = this->nodoSgte->frecuenciaCero - nodoNuevo->frecuenciaCero;
	/*if(r == 1){
		nodoNuevo->frecuenciaCero--;
		this->nodoSgte->frecuenciaCero++;
	}*/

	nodoNuevo->frecuenciaUno = this->nodoSgte->frecuenciaUno * r;
	this->nodoSgte->frecuenciaUno = this->nodoSgte->frecuenciaUno - nodoNuevo->frecuenciaUno;
	/*if(r == 1){
		nodoNuevo->frecuenciaUno--;
		this->nodoSgte->frecuenciaUno++;
	}*/

	nodoNuevo->nodo0 = this->nodoSgte->nodo0;
	nodoNuevo->nodo1 = this->nodoSgte->nodo1;

	this->vectorClonados->push_back(nodoNuevo);


	std::cout << "CLONE" << std::endl;

}

void Grafo::clonoSiNecesario(){
	unsigned int apuntanAlHijo = this->nodoSgte->frecuenciaCero + this->nodoSgte->frecuenciaUno;
	if(this->nodoActual->nodo0 == this->nodoSgte){
		if( (this->nodoActual->frecuenciaCero > MINIMO_PARA_CLONAR_1) &&
		( (apuntanAlHijo - this->nodoActual->frecuenciaCero)  > MINIMO_PARA_CLONAR_2)){
			//this->clonar();
			contador++;
		}
	}else{
		if((this->nodoActual->frecuenciaUno > MINIMO_PARA_CLONAR_1) &&
		( (apuntanAlHijo - this->nodoActual->frecuenciaUno)   > MINIMO_PARA_CLONAR_2 )){
			//this->clonar();
			contador++;
		}
	}
}

void Grafo::avanzarConCero(){

	this->nodoSgte = this->nodoActual->nodo0;
	clonoSiNecesario();
	this->nodoActual->frecuenciaCero +=1;
	this->nodoActual = this->nodoActual->nodo0;
}

void Grafo::avanzarConUno(){
	this->nodoActual->frecuenciaUno +=1;
	this->nodoSgte = this->nodoActual->nodo1;
	clonoSiNecesario();
	this->nodoActual = this->nodoActual->nodo1;
}
